package com.powernode.driver.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.powernode.common.constant.SystemConstant;
import com.powernode.common.execption.PowerException;
import com.powernode.common.result.ResultCodeEnum;
import com.powernode.driver.config.TencentProperties;
import com.powernode.driver.mapper.*;
import com.powernode.driver.service.CosService;
import com.powernode.driver.service.DriverInfoService;
import com.powernode.model.entity.driver.*;
import com.powernode.model.form.driver.DriverFaceModelForm;
import com.powernode.model.form.driver.UpdateDriverAuthInfoForm;
import com.powernode.model.vo.driver.DriverAuthInfoVo;
import com.powernode.model.vo.driver.DriverInfoVo;
import com.powernode.model.vo.driver.DriverLoginVo;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.iai.v20180301.IaiClient;
import com.tencentcloudapi.iai.v20180301.models.*;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.Date;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class DriverInfoServiceImpl extends ServiceImpl<DriverInfoMapper, DriverInfo> implements DriverInfoService {
    @Resource
    private WxMaService wxMaService;
    @Resource
    private DriverSetMapper driverSetMapper;
    @Resource
    private DriverAccountMapper driverAccountMapper;
    @Resource
    private DriverLoginLogMapper driverLoginLogMapper;
    @Resource
    private CosService cosService;
    @Resource
    private DriverInfoMapper driverInfoMapper;
    @Resource
    private TencentProperties tencentProperties;
    @Resource
    private DriverFaceRecognitionMapper driverFaceRecognitionMapper;

    /**
     * <p>配送员登录</p>
     * <p>1. 获取用户的微信openId</p>
     * <p>2. 根据openId查询用户</p>
     * <p>3. 若用户不存在，则插入用户信息</p>
     * <p>4. 初始化配送员默认接单数据 driver_set表</p>
     * <p>5. 初始化配送员账户信息 driver_account表</p>
     * <p>6. 记录日志</p>
     */
    @Transactional
    @Override
    public Long login(String code) {
        DriverInfo driverInfo;
        try {
            WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(code);
            String openId = sessionInfo.getOpenid();
            driverInfo = getOne(new LambdaQueryWrapper<DriverInfo>().eq(DriverInfo::getWxOpenId, openId));
            if (driverInfo == null) {
                driverInfo = new DriverInfo();
                driverInfo.setWxOpenId(openId);
                driverInfo.setNickname("刘岩");
                driverInfo.setCreateTime(new Date());
                driverInfo.setAvatarUrl("https://www.shanghairanking.cn/_uni/logo/86980791.png");
                save(driverInfo);
                DriverSet driverSet = new DriverSet();
                driverSet.setDriverId(driverInfo.getId());
                driverSet.setCreateTime(new Date());
                driverSet.setAcceptDistance(new BigDecimal(SystemConstant.ACCEPT_DISTANCE));
                driverSet.setOrderDistance(BigDecimal.ZERO);
                driverSet.setServiceStatus(0);
                driverSet.setIsAutoAccept(0);
                driverSetMapper.insert(driverSet);
                DriverAccount driverAccount = new DriverAccount();
                driverAccount.setDriverId(driverInfo.getId());
                driverAccount.setCreateTime(new Date());
                driverAccountMapper.insert(driverAccount);
            }
            DriverLoginLog driverLoginLog = new DriverLoginLog();
            driverLoginLog.setDriverId(driverInfo.getId());
            driverLoginLog.setCreateTime(new Date());
            driverLoginLog.setMsg("小程序登录");
            driverLoginLogMapper.insert(driverLoginLog);

        } catch (WxErrorException e) {
            throw new RuntimeException(e);
        }
        return driverInfo.getId();
    }

    /**
     * 获取配送员信息
     */
    @Override
    public DriverLoginVo getDriverLoginInfo(Long driverId) {
        //根据主键查询配送员信息
        DriverInfo driverInfo = getById(driverId);
        DriverLoginVo driverLoginVo = new DriverLoginVo();
        BeanUtils.copyProperties(driverInfo, driverLoginVo);
        //是否建立人脸模型
        driverLoginVo.setIsArchiveFace(driverInfo.getFaceModelId() != null);
        return driverLoginVo;
    }

    /**
     * 获取配送员认证信息
     */
    @Override
    public DriverAuthInfoVo getDriverAuthInfo(Long driverId) {
        DriverInfo driverInfo = getById(driverId);
        DriverAuthInfoVo driverAuthInfoVo = new DriverAuthInfoVo();
        BeanUtils.copyProperties(driverInfo, driverAuthInfoVo);
        driverAuthInfoVo.setDriverId(driverInfo.getId());
        driverAuthInfoVo.setIdcardBackShowUrl(cosService.getImageUrl(driverInfo.getIdcardBackUrl()));
        driverAuthInfoVo.setIdcardFrontShowUrl(cosService.getImageUrl(driverInfo.getIdcardFrontUrl()));
        driverAuthInfoVo.setIdcardHandShowUrl(cosService.getImageUrl(driverInfo.getIdcardHandUrl()));
        return driverAuthInfoVo;
    }

    /**
     * 修改配送员认证信息
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean updateDriverAuthInfo(UpdateDriverAuthInfoForm updateDriverAuthInfoForm) {
        DriverInfo driverInfo = new DriverInfo();
        driverInfo.setId(updateDriverAuthInfoForm.getDriverId());
        BeanUtils.copyProperties(updateDriverAuthInfoForm, driverInfo);
        return this.updateById(driverInfo);
    }

    /**
     * 构建配送员人脸库
     */
    @Override
    public Boolean createDriverFaceModel(DriverFaceModelForm driverFaceModelForm) {
        // id获取配送员信息
        DriverInfo driverInfo = driverInfoMapper.selectById(driverFaceModelForm.getDriverId());
        try {
            // 实例化认证对象
            CreatePersonResponse personResponse = getCreatePersonResponse(driverFaceModelForm, driverInfo);
            // 获取faceId
            String faceId = personResponse.getFaceId();
            if (StringUtils.hasText(faceId)) {
                driverInfo.setFaceModelId(faceId);
                driverInfoMapper.updateById(driverInfo);
            }
        } catch (TencentCloudSDKException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    private CreatePersonResponse getCreatePersonResponse(DriverFaceModelForm driverFaceModelForm, DriverInfo driverInfo) throws TencentCloudSDKException {
        IaiClient client = getIaiClient();
        // 实例化请求对象
        CreatePersonRequest req = new CreatePersonRequest();
        req.setGroupId(tencentProperties.getPersionGroupId());
        req.setPersonId(String.valueOf(driverInfo.getId()));
        req.setGender(Long.parseLong(driverInfo.getGender()));
        req.setQualityControl(4L);
        req.setUniquePersonControl(4L);
        req.setPersonName(driverInfo.getName());
        req.setImage(driverFaceModelForm.getImageBase64());
        // 发送请求获取相应
        return client.CreatePerson(req);
    }

    /**
     * 统一创建 IaiClient，避免重复代码
     */
    private IaiClient getIaiClient() {
        Credential cred = new Credential(tencentProperties.getSecretId(), tencentProperties.getSecretKey());
        // 实例化http选项
        HttpProfile httpProfile = new HttpProfile();
        // 指定接入地域域名
        httpProfile.setEndpoint("iai.tencentcloudapi.com");
        // 实例化client选项
        ClientProfile clientProfile = new ClientProfile();
        clientProfile.setHttpProfile(httpProfile);
        // 实例化人脸客户端
        return new IaiClient(cred, tencentProperties.getRegion(), clientProfile);
    }

    /**
     * 获取配送员个性化设置
     */
    @Override
    public DriverSet getDriverSet(Long driverId) {
        LambdaQueryWrapper<DriverSet> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DriverSet::getDriverId, driverId);
        return driverSetMapper.selectOne(queryWrapper);
    }

    /**
     * 查看配送员当天是否进行人脸识别
     */
    @Override
    public Boolean isFaceRecognition(Long driverId) {
        LambdaQueryWrapper<DriverFaceRecognition> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(DriverFaceRecognition::getDriverId, driverId);
        // 查询当天
        queryWrapper.eq(DriverFaceRecognition::getFaceDate, new DateTime().toString("yyyy-MM-dd"));
        long count = driverFaceRecognitionMapper.selectCount(queryWrapper);
        return count != 0;
    }

    /**
     * 人脸验证
     */
    @Override
    public Boolean verifyDriverFace(DriverFaceModelForm driverFaceModelForm) {
        try {
            VerifyFaceResponse resp = getVerifyFaceResponse(driverFaceModelForm);
            System.out.println(VerifyFaceResponse.toJsonString(resp));
            if (resp.getIsMatch()) {
                // 活体检查
                if (this.detectLiveFace(driverFaceModelForm.getImageBase64())) {
                    DriverFaceRecognition driverFaceRecognition = new DriverFaceRecognition();
                    driverFaceRecognition.setDriverId(driverFaceModelForm.getDriverId());
                    driverFaceRecognition.setFaceDate(new Date());
                    driverFaceRecognitionMapper.insert(driverFaceRecognition);
                    return true;
                }
            }
        } catch (TencentCloudSDKException e) {
            log.error("e: ", e);
        }
        throw new PowerException(ResultCodeEnum.FACE_FAIL);
    }

    private VerifyFaceResponse getVerifyFaceResponse(DriverFaceModelForm driverFaceModelForm) throws TencentCloudSDKException {
        IaiClient client = getIaiClient();
        VerifyFaceRequest req = new VerifyFaceRequest();
        req.setImage(driverFaceModelForm.getImageBase64());
        req.setPersonId(String.valueOf(driverFaceModelForm.getDriverId()));
        return client.VerifyFace(req);
    }

    /**
     * 人脸静态活体检测
     */
    private Boolean detectLiveFace(String imageBase64) {
        try {
            IaiClient client = getIaiClient();
            DetectLiveFaceRequest req = new DetectLiveFaceRequest();
            req.setImage(imageBase64);
            DetectLiveFaceResponse resp = client.DetectLiveFace(req);
            System.out.println(DetectLiveFaceResponse.toJsonString(resp));
            if (resp.getIsLiveness())
                return true;
        } catch (TencentCloudSDKException e) {
            log.error("e: ", e);
        }
        return false;
    }

    @Transactional
    @Override
    public Boolean updateServiceStatus(Long driverId, Integer status) {
        LambdaQueryWrapper<DriverSet> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DriverSet::getDriverId, driverId);
        DriverSet driverSet = new DriverSet();
        driverSet.setServiceStatus(status);
        driverSetMapper.update(driverSet, queryWrapper);
        return true;
    }

    @Override
    public DriverInfoVo getDriverInfoOrder(Long driverId) {
        DriverInfo driverInfo = this.getById(driverId);
        DriverInfoVo driverInfoVo = new DriverInfoVo();
        BeanUtils.copyProperties(driverInfo, driverInfoVo);
        //驾龄
        Integer driverLicenseAge = new DateTime().getYear() - new DateTime(driverInfo.getDriverLicenseIssueDate()).getYear() + 1;
        driverInfoVo.setDriverLicenseAge(driverLicenseAge);
        return driverInfoVo;
    }
}